using GLib;

public class environment : Object{
	public fileIndexDB fileIndex;

	public environment(string dbfile){
		fileIndex = new fileIndexDB(dbfile);
	}

	public string[] search(string searchPattern, bool sortByDisplayname){
		return refineSearch (searchPattern, fileIndex.getAllDBnames (), sortByDisplayname);
	}

	public string[] refineSearch(string searchPattern, string[] candidates, bool sortByDisplayname){

		string[] res = new string[0];
		if (!sortByDisplayname){
			foreach (string candidate in candidates){
				if (conditionFulfilled(searchPattern, candidate))
					res += candidate;
			}			
		}else{
			Gee.ArrayList<string> lstResults = new Gee.ArrayList<string>();
			Gee.ArrayList<string> lstResultsDisplayName = new Gee.ArrayList<string>();
			
			foreach (string candidate in candidates){
				if (conditionFulfilled(searchPattern, candidate)){
					string displayName = fileIndex.getValues (candidate, "std_displayname")[0];
					bool added = false;
					for (int q = 0; q < lstResults.size; q++)
						if (displayName < lstResultsDisplayName[q]){
						    lstResults.insert (q, candidate);
						    lstResultsDisplayName.insert (q, displayName);
							added = true;
							break;
						}
					if (!added){//Add if not added yet (because lstResults is empty / all other candidates are < the current)
						lstResults.add (candidate);
						lstResultsDisplayName.add (displayName);
					}
				}
			}
			res = (string[])lstResults.to_array ();
		}

		return res;
	}

	public string[] proposeProperties(string[] candidates){
		string[] proposed = new string[0];
		foreach (string candidate in candidates){
			string[] props = fileIndex.getProperties (candidate);
			foreach (string prop in props){
				if (!(prop in proposed))
					proposed += prop;
			}
		}
		return proposed;
	}

	public string[] proposeValues(string[] candidates, string property){
		string[] proposed = new string[0];
		foreach (string candidate in candidates){
			string[] vals = fileIndex.getValues (candidate, property);
			foreach (string val in vals){
				if (!(val in proposed))
					proposed += val;
			}
		}
		return proposed;
	}


	bool conditionFulfilled(string pattern, string candidate){
		//TODO: Bracket interpretation?

		if ("&" in pattern){
			//Split ANDs and evaluate result

			bool ret = true;
			string[] splt = pattern.split ("&");
			foreach (string s in splt)
				if (!conditionFulfilled (s, candidate))
				ret = false;
			return ret;

		}else if ("|" in pattern){
			//Split ORs and evaluate result

			bool ret = false;
			string[] splt = pattern.split ("|");
			foreach (string s in splt)
				if (conditionFulfilled (s, candidate))
				ret = true;
			return ret;

		}else if ("=" in pattern){
			//Process condition

			string[] splt = pattern.split ("=");
			if (splt.length < 2)//Necessary for possibly empty or wrong pattern string
				return true;

			//Check if candidate has requested property
			if (!(splt[0] in fileIndex.getProperties (candidate))){
				if (splt[1] == "#")
					return true; //Return true if proeprty does not exist and search value is "#"
				else
					return false;
			}
			
			//Check if the candidate's values suffice
			string[] candidateValues = fileIndex.getValues (candidate, splt[0]);
			if (candidateValues.length == 0 && splt[1] == "#")//Return true if search value is "#" and client has no value
				return true;
			
			if (splt[1] in candidateValues)
				return true;
			else
				return false;

		}else
			return true;
	}
}